package com.reebake.ideal.security.authentication;

import cn.hutool.core.collection.CollectionUtil;
import com.reebake.ideal.servlet.core.ResponseBodyWrapper;
import com.reebake.ideal.security.core.LoginSuccessEvent;
import com.reebake.ideal.security.entity.AccessTokenEntity;
import com.reebake.ideal.security.entity.AuthUser;
import com.reebake.ideal.security.entity.LoginSuccessResult;
import com.reebake.ideal.security.properties.ServerSecurityProperties;
import com.reebake.ideal.security.util.JwtAuthUtil;
import com.reebake.ideal.servlet.util.WebUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;

import java.io.IOException;
import java.util.Collection;

@RequiredArgsConstructor
public class LoginAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
    private final ApplicationEventPublisher applicationEventPublisher;
    private final ServerSecurityProperties serverSecurityProperties;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws ServletException, IOException {
        if (!WebUtil.isAjaxRequest(request)) {
            super.onAuthenticationSuccess(request, response, authentication);
        }
        AuthUser authUser = (AuthUser) authentication.getPrincipal();
        LoginSuccessResult loginResult = new LoginSuccessResult();
        Collection<? extends GrantedAuthority> grantedAuthorities = authentication.getAuthorities();
        Collection<String> authorities = CollectionUtil.newHashSet();
        if (CollectionUtil.isNotEmpty(grantedAuthorities)) {
            for (GrantedAuthority grantedAuthority : grantedAuthorities) {
                authorities.add(grantedAuthority.getAuthority());
            }
        }
        AccessTokenEntity accessTokenEntity = JwtAuthUtil.generate(authentication.getName(), authUser.getUserId(), authorities, serverSecurityProperties.getAccessTokenExpireIn());
        loginResult.setAccessToken(accessTokenEntity.getAccessToken());

        LoginSuccessEvent loginSuccessEvent = new LoginSuccessEvent(this, authUser.getUsername(), authUser.getUserId(), null);
        applicationEventPublisher.publishEvent(loginSuccessEvent);

        ResponseBodyWrapper.wrapResponse(response, loginResult);
    }
}
